/******************************************************************************/
/*! 
    Filename
    [Copyright]

    \file
    \namespace    
    \brief      
*/
/******************************************************************************/
/*** Includes *****************************************************************/
//Engine
#include "NDatum.h"
#include "NScope.h"
#include "NMemoryManager.h"

//STL
#include <assert.h>
#include <sstream>
/*** Using ********************************************************************/
using namespace Core;

/*** Macros *******************************************************************/
RTTI_DEFINITIONS(NDatum)
/*** Constants ****************************************************************/

/*** Declarations *************************************************************/

/*** Variables ****************************************************************/

/*** Implementation ***********************************************************/
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
NDatum::NDatum()
	:mSize(0),
	 mCapacity(0),
	 mType(eTYPE_UNKNOWN),
	 mIsExternal(false)
{
	mData.POINTER = NULL;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
NDatum::NDatum(eType type)
	:mSize(0),
	 mCapacity(0),
	 mType(type),
	 mIsExternal(false)
{
	mData.POINTER = NULL;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
NDatum::NDatum(const NDatum & aDatum)
	:mSize(0),
	 mCapacity(0),
	 mType(eTYPE_UNKNOWN),
	 mIsExternal(false)
{
	mData.POINTER = NULL;
	*this = aDatum;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
NDatum::~NDatum()
{
	Clear();
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
unsigned int NDatum::GetNumValues() const
{
	return mSize;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
unsigned int NDatum::GetCapacity() const
{
	return mCapacity;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::isExternal() const
{
	return mIsExternal;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
template<> int&  NDatum::Get<int> ( unsigned int index) const
{
	assert(mType == eTYPE_INT);
	BoundsCheck(index);
	return  mData.INT[index];
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
template<> float&  NDatum::Get<float> ( unsigned int index) const
{
	assert(mType == eTYPE_FLOAT);
	BoundsCheck(index);
	return mData.FLOAT[index];
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
template<> std::string&  NDatum::Get<std::string> ( unsigned int index) const
{
	assert(mType == eTYPE_STRING);
	BoundsCheck(index);
	return mData.STRING[index];
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
template<> NScope*& NDatum::Get<NScope*> ( unsigned int index) const
{
	assert(mType == eTYPE_SCOPE);
	BoundsCheck(index);
	return reinterpret_cast<NScope*&>(mData.SCOPE[index]);
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
template<> NDatum*& NDatum::Get<NDatum*> ( unsigned int index) const
{
	assert(mType == eTYPE_DATUM);
	BoundsCheck(index);
	return mData.DATUM[index];
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
template<> NDatum::Matrix& NDatum::Get<NDatum::Matrix> (unsigned int index) const
{
	assert(mType == eTYPE_MATRIX);
	BoundsCheck(index);
	return mData.MATRIX3[index];
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
///******************************************************************************/
template<> NDatum::Vector&  NDatum::Get<NDatum::Vector> (unsigned int index) const
{
	assert(mType == eTYPE_VECTOR);
	BoundsCheck(index);
	return mData.VECTOR3[index];
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
template<> int& NDatum::Get<int> ( unsigned int index) 
{
	assert(mType == eTYPE_INT);
	BoundsCheck(index);
	return  mData.INT[index];
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
template<> float& NDatum::Get <float> ( unsigned int index) 
{
	assert(mType == eTYPE_FLOAT);
	BoundsCheck(index);
	return mData.FLOAT[index];
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
template<>  std::string& NDatum::Get<std::string> ( unsigned int index)
{
	assert(mType == eTYPE_STRING);
	BoundsCheck(index);
	return mData.STRING[index];
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
template<> NDatum*& NDatum::Get <NDatum*> ( unsigned int index) 
{
	assert(mType == eTYPE_DATUM);
	BoundsCheck(index);
	return mData.DATUM[index];
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
template<> NScope*& NDatum::Get  <NScope*> ( unsigned int index) 
{
	assert(mType == eTYPE_SCOPE);
	BoundsCheck(index);
	return mData.SCOPE[index];
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
template<> NDatum::Matrix& NDatum::Get<NDatum::Matrix> (unsigned int index)
{
	assert(mType == eTYPE_MATRIX);
	BoundsCheck(index);
	return mData.MATRIX3[index];
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
template<> NDatum::Vector & NDatum::Get<NDatum::Vector> (unsigned int index)
{
	assert(mType == eTYPE_VECTOR);
	BoundsCheck(index);
	return mData.VECTOR3[index];
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
NDatum& NDatum::operator = (const NDatum & aDatum)
{
	if(*this != aDatum) //avoid self assignment
	{
		if(!mIsExternal && !aDatum.mIsExternal) //internal to internal
		{
			Clear();
			mType = aDatum.mType;
			Reserve(aDatum.mCapacity);

			mSize = aDatum.mSize;
			mCapacity  = aDatum.mCapacity;
			Private_Copy(aDatum.mData);
		}
		else if(aDatum.mIsExternal) //internal to external
		{
			Clear();
			mIsExternal = true;
			mSize = aDatum.mSize;
			mCapacity  = aDatum.mCapacity;
			mType = aDatum.mType;
			mData = aDatum.mData;
		}
		else if(mIsExternal && !aDatum.mIsExternal) //external to internal
		{
			Clear();
			mIsExternal = false;
			mType = aDatum.mType;
			mSize = aDatum.mSize;
			mCapacity  = aDatum.mCapacity;

			InitData(aDatum.mCapacity);
			Private_Copy(aDatum.mData);
		}
	}
	return *this;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
NDatum& NDatum::operator = (const int& iValue)
{ 
	Set( iValue ); 
	return *this; 
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/	
NDatum& NDatum::operator = (const float& fValue)
{ 
	Set( fValue ); 
	return *this; 
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/	
NDatum& NDatum::operator = (const std::string& sValue)
{ 
	Set( sValue ); 
	return *this; 
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/	
NDatum& NDatum::operator = (const NScope*& aValue)
{ 
	Set(aValue);
	return *this;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/	
NDatum& NDatum::operator = (const NDatum::Vector& aValue)
{	
	Set(aValue);
	return *this; 
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/	
NDatum& NDatum::operator = (const NDatum::Matrix& aValue)
{	
	Set(aValue);
	return *this; 
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::operator == (const NDatum & aDatum) const
{
	if(mCapacity == aDatum.mCapacity && mSize == aDatum.mSize && mType == aDatum.mType)
	{	
		if(mType == eTYPE_INT)
		{
			for(unsigned j = 0; j < mSize; j++)
			{
				if(mData.INT[j] != aDatum.mData.INT[j])
				{
					return false;
				}
			}
		}
		if(mType == eTYPE_FLOAT)
		{
			for(unsigned j = 0; j < mSize; j++)
			{
				if(mData.FLOAT[j] != aDatum.mData.FLOAT[j])
				{
					return false;
				}
			}
		}
		if(mType == eTYPE_STRING)
		{
			for(unsigned j = 0; j < mSize; j++)
			{
				if(mData.STRING[j] != aDatum.mData.STRING[j])
				{
					return false;
				}
			}
		}
		if(mType == eTYPE_DATUM)
		{
			for(unsigned j = 0; j < mSize; j++)
			{
				if(*mData.DATUM[j] != *aDatum.mData.DATUM[j])
				{
					return false;
				}
			}
		}
		if(mType == eTYPE_POINTER)
		{			
			if( mData.POINTER != aDatum. mData.POINTER)
			{
				return false;
			}
		}
		if(mType == eTYPE_VECTOR)
		{
			//for(unsigned j = 0; j < mSize; j++)
			//{
			//	//if(mData.VECTOR3[j] != aDatum.mData.VECTOR3[j])
			//	{
			//		return false;
			//	}
			//}
		}
		if(mType == eTYPE_MATRIX)
		{
			//for(unsigned j = 0; j < mSize; j++)
			//{
			//	//if(mData.MATRIX3[j] != aDatum.mData.MATRIX3[j])
			//	{
			//		return false;
			//	}
			//}
		}
		if(mType == eTYPE_UNKNOWN)
		{
			return true;
		}
		return true;
	}
	return false;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::operator != (const NDatum & aDatum)const
{
	return !operator == (aDatum);
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::operator == (const int & that ) const 
{
	return (GetNumValues() == 1) && (Get<int>() == that); 
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::operator != (const int & that ) const 
{
	return !operator == ( that ); 
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::operator == (const float & that) const 
{
	return (GetNumValues() == 1) && (Get<float>()  == that); 
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::operator != (const float & that) const 
{
	return !operator == ( that ); 
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::operator == (const std::string& that) const 
{
	return (GetNumValues() == 1) && (Get<std::string>() == that); 
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::operator != (const std::string& that) const 
{
	return !operator == ( that ); 
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::operator == (const NScope& ) const
{
	return true;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::operator != (const NScope& ) const
{
	return true;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::operator == (const NScope* that) const 
{
	return (GetNumValues() == 1) && (Get<NScope*>() == that); 
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::operator != (const NScope* that) const 
{
	return !operator == ( that ); 
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::operator == (const Matrix& ) const 
{
	//return (GetNumValues() == 1) && (Get<Matrix>() == that); 
	return false;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::operator != (const Matrix& that) const 
{
	return !operator == ( that ); 
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
 bool NDatum::operator == (const Vector& ) const 
 {
 	//return (GetNumValues() == 1) && (Get<Vector>() == that); 
	 return false;
 }
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
 bool NDatum::operator != (const Vector&  that) const 
 {
 	return !operator == ( that ); 
 }
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
NDatum::eType NDatum::GetType() const
{
	return mType;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::SetType(eType aType, bool overwrite)
{
	if(mType == aType)
	{
		return;
	}
	assert(mType == eTYPE_UNKNOWN || overwrite);
	if(mType == eTYPE_UNKNOWN || overwrite)
	{	
		mType = aType;	
	}
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::SetNumValues(int numberOfValues)
{
	if(mType == eTYPE_UNKNOWN) 
	{	
		throw std::exception("Type Unknown");	
	}
	Reserve	(numberOfValues);
	if(mSize <= mCapacity || !mIsExternal)
	{ 
		mSize = numberOfValues; //grow for internal of external within capacity
	} 
	else
	{ 
		throw std::exception("Index out of bounds"); 
	}
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::SetStorage(void* array, unsigned int numberOfValues, unsigned int capacity)
{
	if(mCapacity == 0 || mIsExternal)
	{
		if(numberOfValues > capacity) 
		{
			throw std::exception("Number of Values Larger than Capacity");
		}

		mIsExternal = true;
		mType = eTYPE_POINTER;
		mData.POINTER = array;
		mSize = numberOfValues;
		mCapacity = capacity;
	}
	else
	{	
		throw std::exception("Number of Values Larger than Capacity"); 
	}
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::SetStorage(int* array, unsigned int numberOfValues, unsigned int capacity)
{
	if(mCapacity == 0 || mIsExternal)
	{
		if(numberOfValues > capacity) {throw std::exception("Number of Values Larger than Capacity");}
		mIsExternal = true;
		mType = eTYPE_INT;
		mData.INT = array;
		mSize = numberOfValues;
		mCapacity = capacity;
	}
	else
	{
		throw std::exception("Number of Values Larger than Capacity");
	}
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::SetStorage(float*  array, unsigned int numberOfValues, unsigned int capacity)
{
	if(mCapacity == 0 || mIsExternal)
	{
		if(numberOfValues > capacity) 
		{
			throw std::exception("Number of Values Larger than Capacity");
		}

		mIsExternal = true;
		mType = eTYPE_FLOAT;
		mData.FLOAT = array;
		mSize = numberOfValues;
		mCapacity = capacity;
	}
	else
	{
		throw std::exception("Number of Values Larger than Capacity");
	}
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::SetStorage(const std::string* array,unsigned int numberOfValues, unsigned int capacity)
{
	if(mCapacity == 0 || mIsExternal)
	{
		if(numberOfValues > capacity) 
		{
			throw std::exception("Number of Values Larger than Capacity");
		}
		mIsExternal = true;
		mType = eTYPE_STRING;
		mData.STRING = const_cast<std::string*>(array);
		mSize = numberOfValues;
		mCapacity = capacity;
	}
	else
	{
		throw std::exception("Number of Values Larger than Capacity");
	}
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::SetStorage(NScope* array, unsigned int numberOfValues, unsigned int capacity)
{
	if(mCapacity == 0 || mIsExternal)
	{
		if(numberOfValues > capacity) 
		{
			throw std::exception("Number of Values Larger than Capacity");
		}

		mIsExternal	= true;
		mType = eTYPE_SCOPE;

		mData.SCOPE = MY_NEW(Memory::HID_Engine,"NDatum::SetScope::NScope") NScope*[numberOfValues];
		for(unsigned int i = 0; i < numberOfValues;i++)
		{
			mData.SCOPE[i] = &array[i];
		}

		mSize = numberOfValues;
		mCapacity = capacity;
	}
	else
	{
		throw std::exception("Number of Values Larger than Capacity");
	}
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::SetStorage(NDatum* array, unsigned int numberOfValues, unsigned int capacity)
{
	if(mCapacity == 0 || mIsExternal)
	{
		if(numberOfValues > capacity) 
		{
			throw std::exception("Number of Values Larger than Capacity");
		}

		mIsExternal = true;
		mType = eTYPE_DATUM;
		mData.DATUM = &array;
		mSize = numberOfValues;
		mCapacity = capacity;
	}
	else
	{
		throw std::exception("Number of Values Larger than Capacity");
	}
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
 void NDatum::SetStorage(Matrix* array, unsigned int numberOfValues, unsigned int capacity)
 {
 	if(mCapacity == 0 || mIsExternal)
 	{
 		if(numberOfValues > capacity) 
 		{
 			throw std::exception("Number of Values Larger than Capacity");
 		}
 		mIsExternal = true;
 		mType = eTYPE_MATRIX;
 		mData.MATRIX3 = array;
 		mSize = numberOfValues;
 		mCapacity = capacity;
 	}
 	else
 	{
 		throw std::exception("Number of Values Larger than Capacity");
 	}
 }
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
 void NDatum::SetStorage(Vector* array, unsigned int numberOfValues, unsigned int capacity)
 {
 	if(mCapacity == 0 || mIsExternal)
 	{
 		if(numberOfValues > capacity)
 		{
 			throw std::exception("Number of Values Larger than Capacity");
 		}
 
 		mIsExternal = true;
 		mType = eTYPE_VECTOR;
 		mData.VECTOR3 = array;
 		mSize = numberOfValues;
 		mCapacity = capacity;
 	}
 	else
 	{
 		throw std::exception("Number of Values Larger than Capacity");
 	}
 }
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::Set(const int& value, unsigned int index)
{	
	BoundsCheck(index);
	SetType( eTYPE_INT );	
	if(mCapacity == 0)
	{
		SetNumValues(1);
	}
	mData.INT[index] =  value;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::Set(const float& value, unsigned int index)
{
	BoundsCheck(index);
	SetType( eTYPE_FLOAT );
	if(mCapacity == 0)
	{
		SetNumValues(1);
	}
	mData.FLOAT[index] = value;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::Set(const std::string& value, unsigned int index)
{				   
	BoundsCheck(index);
	SetType( eTYPE_STRING );

	if(mCapacity == 0) 
	{
		SetNumValues(1);
	}
	
	mData.STRING[index] =  value;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::Set(const NDatum& value, unsigned int index)
{			   
	BoundsCheck(index);
	SetType( eTYPE_DATUM );

	if(mCapacity == 0) 
	{
		SetNumValues(1);
	}
	*mData.DATUM[index] = value;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::Set(const NScope* value, unsigned int index)
{
	BoundsCheck(index);
	SetType( eTYPE_SCOPE );

	if(mCapacity == 0) 
	{
		SetNumValues(1);
	}
	mData.SCOPE[index] = const_cast<NScope*>(value);
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::Set(const Vector& value, unsigned int index)
{
	BoundsCheck(index);
	SetType( eTYPE_VECTOR );

	if(mCapacity == 0) 
	{
		SetNumValues(1);
	}
	mData.VECTOR3[index] = value;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
 void NDatum::Set(const Matrix & value, unsigned int index)
 {
 	BoundsCheck(index);
 	SetType( eTYPE_MATRIX );
 
 	if(mCapacity == 0) 
 	{
 		SetNumValues(1);
 	}
 	mData.MATRIX3[index] = value;
 }
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::SetFromString(const std::string& value,unsigned int index, eType)
{
	if(mCapacity == 0)
	{		
		SetNumValues(1);
	}
	BoundsCheck(index);

	std::istringstream  intStream;

	switch(mType)
	{
		case eTYPE_INT:
			intStream.str( const_cast<std::string&>( value ).c_str() );
			intStream >> mData.INT[index];
			break;
		case eTYPE_FLOAT:	 
			sscanf_s(value.c_str(), "%f", &mData.FLOAT[index]); 
			break;
		case eTYPE_STRING:   
			mData.STRING[index] = value;
			break;
		case eTYPE_MATRIX:	
			break;
		case eTYPE_VECTOR:	
			break;
		default:
			throw std::exception("Type Unsupported");     
			break;
	}
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
std::string NDatum::GetAsString(const unsigned int index)
{
	std::stringstream stringStream;
	BoundsCheck(index);
	
	char* buffer =  MY_NEW(Memory::HID_Engine,"String") char[100];

	std::string returnValue;
	switch(mType)
	{
		case eTYPE_INT:
			stringStream << mData.INT[index];		
			returnValue  =	stringStream.str().c_str();	
			break;
		case eTYPE_FLOAT:	
			stringStream << mData.FLOAT[index];		
			returnValue  =	stringStream.str().c_str();	
			break;    
		case eTYPE_STRING:   
			returnValue =  mData.STRING[index];		
			break;
		case eTYPE_MATRIX:	
			assert(false); //not tested
			sprintf_s(buffer, 100,"%.4g %.4g %.4g %.4g %.4g %.4g %.4g %.4g %.4g %.4g %.4g %.4g %.4g %.4g %.4g %.4g",							
			mData.MATRIX3[index].at_element(0,0),mData.MATRIX3[index].at_element(0,1),mData.MATRIX3[index].at_element(0,2),mData.MATRIX3[index].at_element(0,3),
			mData.MATRIX3[index].at_element(1,0),mData.MATRIX3[index].at_element(1,1),mData.MATRIX3[index].at_element(1,2),mData.MATRIX3[index].at_element(1,3),
			mData.MATRIX3[index].at_element(2,0),mData.MATRIX3[index].at_element(2,1),mData.MATRIX3[index].at_element(2,2),mData.MATRIX3[index].at_element(2,3),
			mData.MATRIX3[index].at_element(3,0),mData.MATRIX3[index].at_element(3,1),mData.MATRIX3[index].at_element(3,2),mData.MATRIX3[index].at_element(3,3));	
			returnValue = buffer;
			break;														
		case eTYPE_VECTOR:			
			stringStream << mData.VECTOR3[index][0];
			stringStream << ", " << mData.VECTOR3[index][1];
			stringStream << ", " << mData.VECTOR3[index][2];
			returnValue = stringStream.str().c_str();
			break;
		default:
			throw std::exception("Type Unsupported");  
		break;
	}
	return returnValue;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::Reserve(unsigned int newCapacity)
{
	if(newCapacity == 0)
	{
		return;
	}

	//First get memory
	if(!mIsExternal)
	{
		if(newCapacity > mCapacity)
		{
			int			* iTemp;
			float		* fTemp;
			std::string	* cTemp;
			NScope		** sTemp;
			NDatum		* dTemp;
			Matrix		* mTemp;
			Vector		* vTemp;

			mCapacity = newCapacity;

			switch(mType)
			{
				case eTYPE_INT:
					iTemp = MY_NEW(Memory::HID_Engine,"Data::Reserve::Int") int[mCapacity];
					for(unsigned i = 0; i < mSize; i++)
					{
						iTemp[i] =  mData.INT[i];
					}
					if(mData.POINTER != NULL)
					{
						delete  mData.INT;
					}
					mData.INT = iTemp;
					break;
				case eTYPE_FLOAT:
					fTemp = MY_NEW(Memory::HID_Engine,"Data::Reserve::Float") float[mCapacity];
					for(unsigned i = 0; i < mSize; i++)
					{
						fTemp[i] = mData.FLOAT[i];
					}
					if(mData.POINTER != NULL)
					{
						delete mData.FLOAT;
					}
					mData.FLOAT = fTemp;
					break;
				case eTYPE_STRING:
					cTemp = MY_NEW(Memory::HID_Engine,"Data::Reserve::String") std::string[mCapacity];
					for(unsigned i = 0; i < mSize; i++)
					{
						cTemp[i] = mData.STRING[i];
					}
					if(mData.POINTER != NULL)
					{
						delete mData.STRING;
					}
					mData.STRING = cTemp;
					break;
				case eTYPE_DATUM:
					dTemp = MY_NEW(Memory::HID_Engine,"Data::Reserve::NDatum") NDatum[mCapacity];
					for(unsigned i = 0; i < mSize; i++)
					{
						dTemp[i] = *mData.DATUM[i];				
					}
					if(mData.POINTER != NULL)
					{
						delete mData.DATUM;
					}
					mData.DATUM = &dTemp;
					break;
				case eTYPE_SCOPE:
					sTemp = MY_NEW(Memory::HID_Engine,"Data::Reserve::NScope") NScope*[mCapacity];
					for(unsigned i = 0; i < mSize; i++)
					{
						sTemp[i] = mData.SCOPE[i];				
					}
					if(mData.POINTER != NULL)
					{
						delete mData.SCOPE;
					}
					mData.SCOPE = sTemp;
					break;
				case eTYPE_MATRIX:
					mTemp = MY_NEW(Memory::HID_Engine,"Data.Matrix") Matrix[mCapacity];
					for(unsigned i = 0; i < mSize; i++)
					{
						mTemp[i] = mData.MATRIX3[i];				
					}
					if(mData.POINTER != NULL)
					{
						delete mData.MATRIX3;
					}
					mData.MATRIX3 = mTemp;
					break;
				case eTYPE_VECTOR:
					vTemp = MY_NEW(Memory::HID_Engine,"Data.Vector") Vector[mCapacity];
					for(unsigned i = 0; i < mSize; i++)
					{
						vTemp[i] = mData.VECTOR3[i];				
					}
					if(mData.POINTER != NULL)
					{
						delete mData.VECTOR3;
					}
					mData.VECTOR3 = vTemp;
					break;
				default:throw std::exception("Type Invalid");
					break;
			}
		}
	}
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
std::string NDatum::StringFromType(eType	aType)
{
    std::string aString;
	switch(aType)
	{
		case eTYPE_INT:
			aString	= "int";
			break;	
		case eTYPE_FLOAT:
			aString	= "float";
			break;
		case eTYPE_STRING:
			aString	= "string";
			break;
		case eTYPE_POINTER:
			aString	= "pointer";
			break;	
		case eTYPE_DATUM:
			aString = "reference";
			break;
		case eTYPE_SCOPE:
			aString	= "table";
			break;
		case eTYPE_VECTOR:
			aString	= "vector";
			break;
		case eTYPE_MATRIX:
			aString	= "matrix";
			break;
		case eTYPE_UNKNOWN:
			aString	= "unknown";		
			break;
		default:
			throw std::exception("Type Not Supported");
			break;
	}
	return aString;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
NDatum::eType NDatum::TypeFromString(std::string aStringType)
{
	std::string name(aStringType);
	eType aType = eTYPE_UNKNOWN;	

	if(name == "int")			 
	{	
		aType = eTYPE_INT;
	}
	else if(name =="float")
	{	
		aType = eTYPE_FLOAT;
	}
	else if(name == "string") 
	{ 
		aType = eTYPE_STRING;
	}
	else if(name == "pointer")
	{ 
		aType = eTYPE_POINTER;
	}
	else if(name == "reference")
	{
		aType = eTYPE_DATUM;
	}
	else if(name == "table")
	{	
		aType = eTYPE_SCOPE;
	}
	else if(name == "vector")
	{ 
		aType = eTYPE_VECTOR;
	}
	else if(name == "matrix")
	{ 
		aType = eTYPE_MATRIX;
	}
	return aType;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::ReferenceHasValue(const NDatum & aDatum)
{
	if(aDatum.mCapacity != NULL)
	{
		if( aDatum.mData.DATUM != NULL)
		{
			return true;
		}
	}
	return false;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
bool NDatum::HasValue(const NDatum & aDatum,unsigned int index)
{
	if(aDatum.mCapacity != NULL)
	{	
		if(aDatum.GetCapacity() > index)
		{
			return true;
		}
	}
	return false;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::Private_Copy(const uData& source)
{
	switch(mType)
		{
		case eTYPE_INT:
			for(unsigned i = 0; i < mSize; i++)
			{
					mData.INT[i] = source.INT[i];
			}
			break;
		case eTYPE_FLOAT:
			for(unsigned i = 0; i < mSize; i++)
			{
				mData.FLOAT[i] = source.FLOAT[i];
			}
			break;
		case eTYPE_STRING:
			for(unsigned i = 0; i < mSize; i++)
			{
				mData.STRING[i] = source.STRING[i];
			}
			break;
		case eTYPE_DATUM:
			for(unsigned i = 0; i < mSize;i ++)
			{
				mData.DATUM[i] = source.DATUM[i];
			}
			break;
		case eTYPE_POINTER:
				mData.POINTER = source.POINTER;
			break;
		case eTYPE_SCOPE:
			for(unsigned i = 0; i < mSize;i ++)
			{
				mData.SCOPE[i] = source.SCOPE[i];
			}
			break;
		case eTYPE_MATRIX:
			for(unsigned i = 0; i < mSize; i++)
			{
				//mData.MATRIX3[i] = source.MATRIX3[i];
			}
			break;
		case eTYPE_VECTOR:
			for(unsigned i = 0; i < mSize; i++)
			{
				//mData.VECTOR3[i] = source.VECTOR3[i];
			}
			break;
		case eTYPE_UNKNOWN:

			break;
		default:throw std::exception("Type Invalid");
			break;
		}	

}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::Clear()
{
	if(!mIsExternal && mData.POINTER != NULL)
	{
		switch(mType)
		{
		case eTYPE_INT:	     
			MY_DELETE_ARRAY( mData.INT );
			break;
		case eTYPE_FLOAT:	 
			MY_DELETE_ARRAY( mData.FLOAT );
			break;
		case eTYPE_STRING:
			MY_DELETE_ARRAY( mData.STRING );
			break;
		case eTYPE_DATUM: 
			MY_DELETE_ARRAY( mData.DATUM );
			break;
		case eTYPE_VECTOR:	 
			MY_DELETE_ARRAY( mData.VECTOR3 );
			break;
		case eTYPE_MATRIX:	 
			MY_DELETE_ARRAY( mData.MATRIX3 );
			break;
		case eTYPE_SCOPE:
			MY_DELETE_ARRAY( mData.SCOPE );
			break;
		case eTYPE_UNKNOWN:
			break;
		default:
			throw std::exception("Delete Failed");
			break;
		}
	}
	else
	{
		if(mCapacity > 0)
		{
			switch(mType)
			{
				case eTYPE_SCOPE:
					MY_DELETE_ARRAY( mData.SCOPE );
					break;
			}
		}
	}
	mData.POINTER = NULL;
	mType = eTYPE_UNKNOWN;
	mCapacity = 0;
	mSize = 0;
	mIsExternal = false;
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::BoundsCheck( unsigned int index) const
{
	if(index > mSize-1)
	{
		throw std::exception("Index out of bounds");
	}
}
/******************************************************************************/
/*! Attributed :: [Function]

    \brief  

    \param  
    \return
*/
/******************************************************************************/
void NDatum::InitData(int newCapacity)
{
	if(newCapacity == 0)
	{
		return;
	}
	switch(mType)
	{
		case eTYPE_INT:	       
			mData.INT  = MY_NEW(Memory::HID_Engine,"NDatum::InitData::TypeInt") int[newCapacity]();			 
			break;
		case eTYPE_FLOAT:	   
			mData.FLOAT  = MY_NEW(Memory::HID_Engine,"NDatum::InitData::TypeFloat") float[newCapacity]();		
			break;
		case eTYPE_STRING:      
			mData.STRING  = MY_NEW(Memory::HID_Engine,"NDatum::InitData::TypeString") std::string[newCapacity]();		
			break;
		case eTYPE_DATUM:   
			mData.DATUM  = MY_NEW(Memory::HID_Engine,"NDatum::InitData::NDatum") NDatum*[1];   	
			break;
		case eTYPE_SCOPE:
			mData.SCOPE = MY_NEW(Memory::HID_Engine,"NDatum::InitData::NScope") NScope*[1];
			break;
		case eTYPE_MATRIX:	   
			mData.MATRIX3  = MY_NEW(Memory::HID_Engine,"NDatum::InitData::Matrix") Matrix[newCapacity]();		 
			break;
		case eTYPE_VECTOR:	   
			mData.VECTOR3  = MY_NEW(Memory::HID_Engine,"NDatum::InitData::Vector") Vector[newCapacity]();		 
			break;
		case eTYPE_UNKNOWN:	
			break;
		default:
			throw std::exception("Type Invalid");
			break;
	}
	mCapacity = newCapacity;
}